import md5 from 'react-native-md5';

import { SQLError } from '../common/wcdb';
import DataBase, { RowData } from '../common/db';
import Log from '../common/log';
import { DEVICE_ID } from '../constant';

const TAG = 'UserTable';
export const USER_DB_USER_INFO = 'userInfo';
export const USER_DB_TEST_RECORD = 'testRecord';
export const USER_DB_HISTORY_TEST = 'historyTest';
export const USER_DB_TEST_PAPER_RECORD = 'testPaperRecord';
export const USER_DB_CHAPTER_EXERCISE_RECORD = 'chapterExerciseRecord';
export const USER_DB_HISTORY_CHAPTER_EXERCISE = 'historyChapterExercise';

const UserDB = new DataBase();

class UserTable {
  private isConnect = false;

  public getConnectStatus(): boolean {
    return this.isConnect;
  }

  public disconnect(): void {
    this.isConnect = false;
  }

  public connect(userId: string): Promise<void> {
    return new Promise((resolve, reject): void => {
      const signature = md5.hex_md5(`${DEVICE_ID}${userId}`);
      const name = md5.hex_md5(`${userId}`);
      UserDB.connect({ dbName: `${name}.db`, key: signature })
        .then((): void => {
          this.isConnect = true;
          this.initUserTable(USER_DB_USER_INFO);
          this.init(USER_DB_TEST_RECORD, 'examId');
          this.init(USER_DB_HISTORY_TEST, 'examId');
          this.init(USER_DB_TEST_PAPER_RECORD, 'examPaperId');
          this.init(USER_DB_CHAPTER_EXERCISE_RECORD, 'chapterExerciseId');
          this.init(USER_DB_HISTORY_CHAPTER_EXERCISE, 'chapterExerciseId');
          resolve();
        })
        .catch((): void => {
          reject();
        });
    });
  }

  public initUserTable(table: string): void {
    UserDB.createTable(
      `CREATE TABLE IF NOT EXISTS ${table}(` +
        'uid integer primary key,' +
        'content string' +
        ')'
    )
      .then((): void => {
        Log.i(TAG, 'init database succ');
      })
      .catch((err: SQLError): void => {
        Log.e(TAG, JSON.stringify({ desc: 'init', err }));
      });
  }

  public init(table: string, key: string): void {
    UserDB.createTable(
      `CREATE TABLE IF NOT EXISTS ${table}(` +
        `${key} integer primary key,` +
        'content string' +
        ')'
    )
      .then((): void => {
        Log.i(TAG, 'init database succ');
      })
      .catch((err: SQLError): void => {
        Log.e(TAG, JSON.stringify({ desc: 'init', err }));
      });
  }

  public load(table: string): Promise<RowData[]> {
    return new Promise((resolve, reject): void => {
      UserDB.query(`select * from ${table}`)
        .then((datas: RowData[]): void => {
          Log.i(TAG, `load n=${datas}`);
          resolve(datas);
        })
        .catch((err: SQLError): void => {
          Log.e(TAG, JSON.stringify({ desc: 'load', err }));
          reject(err);
        });
    });
  }

  public clear(table: string, key: string, id: number): Promise<number> {
    const sql = `DELETE FROM ${table} WHERE ${key} = ${id}`;
    return new Promise((resolve, reject): void => {
      UserDB.execute(sql)
        .then((numAffected: number): void => {
          Log.i(TAG, `clearUtil n=${numAffected}`);
          resolve(numAffected);
        })
        .catch((err: SQLError): void => {
          Log.e(TAG, JSON.stringify({ desc: 'clear', err }));
          reject(err);
        });
    });
  }

  public clearAll(table: string): Promise<number> {
    const sql = `DELETE FROM ${table}`;
    return new Promise((resolve, reject): void => {
      UserDB.execute(sql)
        .then((numAffected: number): void => {
          Log.i(TAG, `clearUtil n=${numAffected}`);
          resolve(numAffected);
        })
        .catch((err: SQLError): void => {
          Log.e(TAG, JSON.stringify({ desc: 'clearAll', err }));
          reject(err);
        });
    });
  }

  public replace(table: string, info: RowData): Promise<number> {
    return new Promise((resolve, reject): void => {
      UserDB.replace(table, info)
        .then((numAffected: number): void => {
          Log.i(TAG, `replace n=${numAffected}`);
          resolve(numAffected);
        })
        .catch((err: SQLError): void => {
          Log.e(TAG, JSON.stringify({ desc: 'replace', err }));
          reject(err);
        });
    });
  }
}

const userTable = new UserTable();

export default userTable;
